每個工作節點上負責監控Pod存活性的角色是kubelet, 它會在主容器發生錯誤時進行自我修復, 但它只能監控主容器, 其餘的項目發生錯誤時需要依靠Pod設定的存活性探測機制來得知,
但是在工作節點自身發生錯誤的時候kubelet也不能再使用了, 此時Master無法得知工作節點的狀態, Pod也無法再重啟; 這時候就需要透過工作節點之外的Controller來監控, Controller是K8s Master的 kube-controller-manager上的一個組件, kube-controller-manager的任務是要確保object的status
要符合object部署的spec
, 它會不斷的進行status
和spec
的和解reconciliation
來確保Pod的狀態, 常見的controller有 Namespace Controller
, Deployment Controller
, Service Controller
...等, 可以將 Pod Controller視為一個監督者的角色, 它位在Pod工作節點外的上一層, 負責確保Pod有依照用戶設定的內容運作。
圖片參考書:【Kubernetes 進階實踐】
Pod模板是Controller拿來創建或管理Pod的參考規範,Pod spec
通常都必須具備replicas
,selector
,template
, 模板就是spec
中的 template
字段; 由於template
是要嵌入Controller中使用, 所以不會有apiVersion
, kind
字段,
修改或更新template
並不會更新已存在的Pod, 而是由Controller偵測到spec更新而創建一個新的Pod, 同時檢查Pod的狀態是否符合spec
, 不符合spec
的pod 將會被終止。
ReplicaSet 是用來確保Pod的運作狀態要符合pod spec配置的一種實現, 它啟動後會在cluster中匹配和 label selector 相符的object, 並反覆確認pod個數是否符合spec期望, 如果有多會刪除, 有少則會透過 PodTemplate 創建Pod補足, 等到狀態符合期望之後, ReplicaSet 會再進入下一個循環。
圖片參考書:【Kubernetes 進階實踐】
配置 ReplicaSet spec
一樣需要 apiVersion
, kind
, metadata
, spec
, 針對 spec
底下還有幾個屬性:
* replicas : 期望的pod數量
* selector : Controller匹配Pod數量的label selector, 支援 matchLabels
和 matchExpressions
* template : 用來補足Pod數量時所用的Pod模板
* minReadySeconds : 新建的Pod在啟動後多長時間內未發生錯誤即視為Ready
, 預設0秒。
### 創建範例 YAML
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: rs-example
spec:
replicas: 2
selector:
matchLabels:
app: rs-demo
template:
metadata:
labels:
app: rs-demo
spec:
containers:
- name: rs-hello
image: nginx:latest
ports:
- name: http
containerPort: 80
minReadySeconds: 5
執行
-> % kubectl apply -f replica-demo.yaml
replicaset.apps/rs-example configured
查看狀態
-> % kubectl get pods -l app=rs-demo
NAME READY STATUS RESTARTS AGE
rs-example-44nhn 0/1 ContainerCreating 0 4s
rs-example-mgjcr 0/1 ContainerCreating 0 4s
第一次key錯image, 查看狀態時回應如下
-> % kubectl get pods -l app=rs-demo
NAME READY STATUS RESTARTS AGE
rs-example-44nhn 0/1 ErrImagePull 0 11s
rs-example-mgjcr 0/1 ErrImagePull 0 11s
修改image來源之後查看狀態還是不成功(因為replicaSet的YAML修改只對新建的pod生效
)
-> % kubectl get pods -l app=rs-demo
NAME READY STATUS RESTARTS AGE
rs-example-44nhn 0/1 ImagePullBackOff 0 28s
rs-example-mgjcr 0/1 ImagePullBackOff 0 28s
此時操作刪除Pod讓它自動重新建立
kubectl delete pod rs-example-mgjcr
kubectl delete pod rs-example-44nhn
載入修改後image的pod狀態已是Running
-> % kubectl get pods -l app=rs-demo
NAME READY STATUS RESTARTS AGE
rs-example-nvwqp 1/1 Running 0 9s
rs-example-tcckz 1/1 Running 0 18s
Pod創建後, ReplicaSet就不會再去檢查pod spec內容, 所以除了修改pod副本個數之外, 其餘的變動都要在下一個新的pod創建時才會生效。ReplicaSet 可以確保Pod數量精確符合期望值, 發現Pod不健康時會自動請求創建Pod副本以及隨著設定彈性伸縮pod規模。
ReplicaSet 是按照 label selector 來匹配pod數量, 如果手動去修改 label 也會觸發 ReplicaSet 自動創建的機制
-> % kubectl get pods -L app
NAME READY STATUS RESTARTS AGE APP
rs-example-cwn9x 1/1 Running 0 4m14s rs-demo
rs-example-jbm28 1/1 Running 0 4m14s rs-demo
-> % kubectl label pods rs-example-cwn9x app= --overwrite
pod/rs-example-cwn9x labeled
-> % kubectl get pods -L app
NAME READY STATUS RESTARTS AGE APP
rs-example-cwn9x 1/1 Running 0 5m26s
rs-example-jbm28 1/1 Running 0 4m59s rs-demo
rs-example-v94sf 1/1 Running 0 13s rs-demo
原本的 rs-example-cwn9x 因為強制更新了label 所以ReplicaSet檢查的時候不會計算它, 為了達到期望的2個, 於是創建了一個新的 rs-example-v94sf
-> % kubectl label pods rs-example-cwn9x app=rs-demo --overwrite
pod/rs-example-cwn9x labeled
-> % kubectl get pods -L app
NAME READY STATUS RESTARTS AGE APP
rs-example-cwn9x 1/1 Running 0 9m28s rs-demo
rs-example-jbm28 1/1 Running 0 9m1s rs-demo
rs-example-v94sf 0/1 Terminating 0 4m15s rs-demo
因為 rs-example 只能有兩個pod, 當 label掃到有三個pod的時候, 會把其中一個pod刪除, 所以 rs-example-v94sf 狀態為 Terminating
kubectl 提供了一個指令可以實現 ReplicaSet 的伸縮
kubectl scale replicasets [LABEL] --replicas=<integer>
-> % kubectl get replicasets
NAME DESIRED CURRENT READY AGE
rs-example 2 2 2 50m
-> % kubectl scale replicasets rs-example --replicas=3
replicaset.apps/rs-example scaled
-> % kubectl get replicasets
NAME DESIRED CURRENT READY AGE
rs-example 3 3 3 51m
另外kubectl 還提供參數 --current-replicas
可以依照現在pod數量判斷擴充條件
--current-replicas
條件所以不會執行-> % kubectl scale replicasets rs-example --current-replicas=2 --replicas=3
error: Expected replicas to be 2, was 3
-> % kubectl scale replicasets rs-example --current-replicas=3 --replicas=5
replicaset.apps/rs-example scaled
-> % kubectl get replicasets
NAME DESIRED CURRENT READY AGE
rs-example 5 5 5 57m
預設刪除ReplicaSet 時會一併刪除下層的pod, kubectl 有提供參數 --cascade=false
供使用, 可以只刪除 replicaset
由於replicaset不支援滾動更新,所以大多建議使用deployment,下一篇會研究看看deployment。